#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <errno.h>
#include <time.h>

#define SERVER "127.0.0.25"
#define PORT   9000

static void
error(char *msg)
{
    fputs(strerror(errno), stderr);
    fputs(": ", stderr);
    fputs(msg, stderr);
    fputc('\n', stderr);
    exit(1);
}

int main(int argc, char **argv)
{
    int z;	//status return code
    char *srvr_addr = NULL;

    struct sockaddr_in adr_inet;	//server socket address
    struct sockaddr_in adr_clnt;	//client socket address

    size_t len_inet;			//length of server socket address
    int s;				//server socket fd

    char dgram[512];			//received buffer
    char dtfmt[512];			//formated date and time

    time_t td;				//current date and time
    struct tm tm;			//date and time values

    if ( argc >= 2) {
	srvr_addr = argv[1];
    } else {
	srvr_addr = SERVER;
    }

    //create udp socket
    s = socket(AF_INET, SOCK_DGRAM, 0);
    if ( s == -1 )
	error("socket()");

    //create socket address
    memset(&adr_inet, 0, sizeof(adr_inet));
    adr_inet.sin_family = AF_INET;
    adr_inet.sin_port = htons(PORT);
    if ( inet_aton(srvr_addr, &adr_inet.sin_addr) == -1 )
	error("inet_aton()");

    len_inet = sizeof(adr_inet);

    //bind socket to the address so client program can connect to the server
    z = bind(s, (struct sockaddr *) &adr_inet, len_inet);
    if ( z == -1 )
	error("bind()");
    
    //now wait for the requests
    for (;;) {
	//block until the program receives datagram at out address and port
	len_inet = sizeof(adr_clnt);
	z = recvfrom(s, dgram, sizeof(dgram), 0, (struct sockaddr *) &adr_clnt, &len_inet);
	if ( z < 0 )
	    error("recvfrom()");

	//null terminate the string
	dgram[z] = 0;

	if( ! strcasecmp(dgram, "QUIT") )
	    break;		// quit server

	//get the current date and time
	time(&td);
	tm = *localtime(&td);	//get time components;

	//format new date and time string
	strftime(dtfmt, sizeof dtfmt, dgram, &tm);

	//send formatted result back to the client
	z = sendto(s, dtfmt, strlen(dtfmt), 0, (struct sockaddr *) &adr_clnt, len_inet);
	if ( z < 0 )
	    error("sendto()");
    }

    //close the socket
    close(s);

    return 0;
}
